home *** CD-ROM | disk | FTP | other *** search
- _PROGRAMMING WITH COMMUNCIATION PROTOCOL STACKS_
- by Gordon Free
-
- [LISTING ONE]
-
- #ifndef FT_H
- #define FT_H
-
- #define HVC_FIRST 2
- #define HVC_LAST 5
- #define MAX_VCS HVC_LAST-HVC_FIRST+1
- #define HDRSIZE MAX_APPHDRDATA+sizeof(BBHDR)
-
- /* Message command values */
- #define FT2_SEND 3
- #define FT2_RECEIVE 4
-
- /* Bit fields for Blackbird events */
- typedef union {
- struct {
- unsigned ListenCallback : 1;
- unsigned ConnectCallback : 1;
- unsigned ReadBreathe : 1;
- unsigned ReadCallback : 1;
- unsigned WriteBreathe : 1;
- unsigned WriteCallback : 1;
- unsigned DisconnectCallback : 1;
- } flags;
- int all;
- } EVENT_T;
-
- /* Structure for info on currently open file */
- typedef struct _FILEDATA {
- FILE *hStream; /* stream handle */
- char *pszName; /* name of file */
- char *pszOpenMode; /* mode file is opened in "r", "w", etc. */
- long lSize; /* size of file in bytes */
- void *pvBuffer; /* ptr to buffer of file contents */
- } FILEDATA_T;
-
- /* Structure for application service, one per VC */
- typedef struct _SVCDATA {
- FILEDATA_T fdCurFile; /* current file info */
- char bbhXmit[HDRSIZE]; /* BB hdr for sending */
- char bbhRcv[HDRSIZE]; /* BB hdr for rcving */
- char *pszRemoteName; /* name of remote machine */
- long lBytesSoFar; /* num bytes xferred */
- int fActive; /* TRUE if VC is active */
- short sStatus; /* status of last BB event */
- EVENT_T fEvent; /* BB event flags */
- } SVCDATA_T;
-
- /*----- Callback routine prototypes ------*/
- void cbRemService (
- unsigned usNumSvcs /* Number of remote services */
- );
- SHORT cbListen (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Nothing at this time */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- );
- SHORT cbConnect (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Nothing at this time */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- );
- SHORT cbDisConnect (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Nothing at this time */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- );
- SHORT cbRead (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Number of bytes read */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- );
- SHORT cbWrite (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Number of bytes sent */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- );
- #endif
-
-
-
- [LISTING TWO]
-
- /*====================================================================
- (c) Copyright 1991, Gordon Free
- All Rights Reserved.
- --------------------------------------------------------------------
- Filename: FT.C
- Project: DDJ Article
- $Author$
- $Revision$
- $Date$
- Purpose: Sample file transfer program written for Blackbird API.
- ====================================================================*/
-
- /*----- Includes ------*/
- #include <stdio.h>
- #include <conio.h>
- #include <malloc.h>
- #include <string.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <io.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include "vcapi.h"
- #include "ft.h"
-
- /*----- Local Defines and Typedefs ------ */
- #define ESC 0x1B
- #define BUFF_SIZE (64*1024-1)
-
- /*------ Global Variables -----*/
- int fUpdateServices=FALSE; /* remote service list has changed */
- HANDLE hvcServer=HVC_NONE; /* vc handle of remote server */
- SVCDATA_T svc[MAX_VCS]; /* array of app service info */
- char acMachineName[MAX_MACHID] = "Unknown";
-
- /*---- DisplayServices: prints a report of all available remote services ----*/
- void DisplayServices(void)
- {
- int nServices; /* num of services reported */
- REMSERVICES remserv; /* service info struct */
- static HANDLE ahRS[10]; /* array of remote svc handles */
- int i;
-
- puts("\nList of Remote Machines ...");
- puts("---------------------------");
-
- /* Fill in array of remote service handles */
- nServices = vcQuery(ahRS, HBOUND(ahRS));
-
- /* Report service handle and machine name for each remote service */
- for (i=0; i<nServices; i++) {
- sGetRemSvc(ahRS[i], &remserv);
- printf(" %d) %s on %s %c\n", ahRS[i], remserv.acMachineName
- , remserv.acPortName
- , remserv.fInUse ? '*' : ' ');
- }
- }
-
- /*-- SendFile: read specified file and hand it to Blackbird for delivery --*/
- size_t SendFile (
- HANDLE vch, /* handle of virtual connection */
- char *name /* name of file */
- )
- {
- int size=0; /* number of bytes read */
- int fileOut; /* file stream to read from */
- PBBHDR pbbhXmit; /* ptr to BB header */
- SVCDATA_T *psvc; /* ptr to service struct for this vc */
-
- printf("Sending %s ...\n", name);
- fileOut = open(name,O_RDONLY|O_BINARY);
- if (fileOut > 0) {
- psvc = &svc[vch-HVC_FIRST];
-
- /* Read contents of file into buffer */
- size = read(fileOut, psvc->fdCurFile.pvBuffer, BUFF_SIZE);
- close(fileOut);
-
- /* Put name into packet header */
- pbbhXmit = (PBBHDR)&(psvc->bbhXmit[0]);
- strcpy(&(pbbhXmit->bAppData[1]), name);
-
- /* Indicate what remote is to do with this data */
- pbbhXmit->bAppData[0] = FT2_RECEIVE;
- pbbhXmit->ubBytesToFollow = strlen(name)+2;
-
- vcWrite(vch,pbbhXmit, psvc->fdCurFile.pvBuffer, size
- , NULL, cbWrite, TWO_SECS);
-
- } else {
- perror("Error opening file");
- }
- return size;
- }
-
- /*----SaveFile: write contents of buffer into file with specified name----*/
- int SaveFile (
- char *name,
- long lsize,
- void far *buffer
- )
- {
- int size;
- int fileIn;
- printf("Saved file = %s\n", name);
- fileIn = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY);
- if (fileIn > 0) {
- size = (size_t) lsize;
- write(fileIn, buffer, size);
- close(fileIn);
- } else {
- perror("Error saving file");
- }
- return 0;
- }
-
- /*---CheckEvents: polls each virtual connection looking for events that
- have been flagged by the various callback routines.---*/
- void CheckEvents ( void )
- {
- EVENT_T evt;
- SVCDATA_T *psvc;
- PBBHDR pbbhRcv;
- HANDLE vch;
- void *buff;
- int i;
- /* Loop through all possible virtual connections */
- for (i=0, psvc=svc; i<MAX_VCS; i++, psvc++) {
- /* Check to see if anything happened */
- if (psvc->fEvent.all) {
- /* Get copy of event flags and then reset them. This is done with
- /* interrupts disabled so that we don't miss any events. */
- _disable();
- evt = psvc->fEvent;
- psvc->fEvent.all = FALSE;
- _enable();
-
- /* ------------------- Listen --------------------------- */
- /* Somebody connected to us, allocate storage and issue a */
- /* read to get file transfer requests. */
- if (evt.flags.ListenCallback) {
- puts("#Listen Callback");
- pbbhRcv = (PBBHDR)&(psvc->bbhRcv[0]);
- if (psvc->fdCurFile.pvBuffer != NULL) {
- vcRead(HVC_FIRST+i,pbbhRcv, psvc->fdCurFile.pvBuffer
- , BUFF_SIZE, NULL, cbRead, TWO_SECS);
- } else {
- puts("Error allocating memory");
- }
- /* Register a new service for use by other clients */
- buff = malloc(BUFF_SIZE);
- if (buff != NULL) {
- vch = vcListen ("FXFR","DDJ", cbListen, cbDisConnect);
- svc[vch-HVC_FIRST].fdCurFile.pvBuffer = buff;
- } else {
- puts("Error allocating memory");
- }
- }
-
- /* ------------------- Connect -------------------------- */
- /* We've successfully connected to a remote server */
- if (evt.flags.ConnectCallback) {
- puts("#Connect Callback");
- hvcServer = HVC_FIRST+i;
- }
-
- /* ------------------- Read --------------------------- */
- /* We've gotten a request, so process it! */
- if ((evt.flags.ReadCallback) && (psvc->sStatus == 0)) {
-
- pbbhRcv = (PBBHDR)&(psvc->bbhRcv[0]);
- /* Is it a request to receive a file? */
- if (pbbhRcv->bAppData[0] == FT2_RECEIVE) {
- SaveFile(&(pbbhRcv->bAppData[1]), psvc->lBytesSoFar
- , psvc->fdCurFile.pvBuffer);
- /* How about send a file? */
- } else if (pbbhRcv->bAppData[0] == FT2_SEND) {
- SendFile(i+HVC_FIRST, &(pbbhRcv->bAppData[1]));
- /* No comprende */
- } else {
- puts("Huh?");
- }
- vcRead(HVC_FIRST+i,pbbhRcv, psvc->fdCurFile.pvBuffer
- , BUFF_SIZE, NULL, cbRead, TWO_SECS);
- }
-
- /* ------------------- Write --------------------------- */
- if ((evt.flags.WriteCallback) && (psvc->sStatus == 0)) {
- puts("#Write Complete");
- }
-
- /* ------------------- Disconnect ---------------------- */
- /* Remote went byebye */
- if (evt.flags.DisconnectCallback) {
- puts("#Disconnect Callback");
- free(psvc->fdCurFile.pvBuffer);
- if (i+HVC_FIRST == hvcServer)
- hvcServer = HVC_NONE;
- }
- }
- }
- if (fUpdateServices) {
- fUpdateServices = FALSE;
- DisplayServices();
- }
- }
-
- /*---DoUserRequests: check keyboard for activity and process user's
- command. Returns TRUE if user has not requested to exit.---*/
- int DoUserRequests ( void )
- {
- HANDLE vch;
- SVCDATA_T *psvc;
- PBBHDR pbbhXmit, pbbhRcv;
- int fContinue=TRUE;
- char filename[80];
- void *buff;
- int c;
-
- if ( kbhit() ) {
- switch (c = getch()) {
-
- /* ------------------- Exit ----------------------------- */
- case ESC:
- fContinue = FALSE;
- break;
-
- /* ------------------- Connect -------------------------- */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
-
- /* Disconnect from current server, if any. */
- /* Buffer will be released when disconnect completes */
- if (hvcServer != HVC_NONE) {
- vcDisconnect(hvcServer);
- }
- /* Allocate buffer for new service */
- buff = malloc(BUFF_SIZE);
- if (buff != NULL) {
- /* Connect to remote server */
- vch = vcConnect(c-'0', cbConnect, cbDisConnect, TWO_SECS);
- svc[vch-HVC_FIRST].fdCurFile.pvBuffer = buff;
- } else {
- puts("Error allocating memory");
- }
- break;
-
- /* ------------------- Send File ------------------------ */
- case 's':
- case 'S':
- if (hvcServer != HVC_NONE) {
- psvc = &svc[hvcServer-HVC_FIRST];
- printf("\nEnter name of file to send >");
- scanf("%s", filename);
- SendFile(hvcServer, filename);
- } else {
- puts("You must establish a connection first!");
- }
- break;
-
- /* ------------------- Receive File --------------------- */
- case 'r':
- case 'R':
- if (hvcServer != HVC_NONE) {
- psvc = &svc[hvcServer-HVC_FIRST];
-
- /* Set up ptrs to BB hdrs for receive and send */
- pbbhXmit = (PBBHDR)&(psvc->bbhXmit[0]);
- pbbhRcv = (PBBHDR)&(psvc->bbhRcv[0]);
-
- /* Instruct remote server to send specified file */
- printf("\nEnter name of file to receive >");
- scanf("%s", &(pbbhXmit->bAppData[1]));
- pbbhXmit->bAppData[0] = FT2_SEND;
-
- pbbhXmit->ubBytesToFollow
- = strlen(&(pbbhXmit->bAppData[1]))+2;
- /* Post read before sending request so that we are ready */
- /* for response */
- vcRead(hvcServer,pbbhRcv, psvc->fdCurFile.pvBuffer
- , BUFF_SIZE, NULL, cbRead, TWO_SECS);
- /* Send request for file */
- vcWrite(hvcServer,pbbhXmit, NULL, 0, NULL, cbWrite, TWO_SECS);
- } else {
- puts("You must establish a connection first!");
- }
- default:
- break;
- }
-
- }
- return fContinue;
- }
-
- /*----main: initalize Blackbird and alternate between processing Blackbird
- events and user requests. ----*/
- int main (
- int argc,
- char **argv
- )
- {
- HANDLE vch;
- void *buff;
- puts("Blackbird File Transfer Sample Program ver 1.0");
- puts(" (c) Copyright 1991, Gordon Free.");
- puts(" All Rights Reserved.\n");
- puts(vcVersion());
-
- /* Parse machine name off command line */
- if (argc >= 2) {
- strncpy(acMachineName, argv[1], sizeof(acMachineName-1));
- acMachineName[sizeof(acMachineName-1)] = '\0';
- }
-
- /* Initialize Blackbird and request notification of remote services */
- vcInit(acMachineName,"DDJ");
- vcRemsvcUpdate(cbRemService);
-
- /* Register as a server only if user gave a machine name */
- if (argc >= 2) {
- buff = malloc(BUFF_SIZE);
- if (buff != NULL) {
- vch = vcListen ("FXFR","DDJ", cbListen, cbDisConnect);
- svc[vch-HVC_FIRST].fdCurFile.pvBuffer = buff;
- } else {
- puts("Error allocating memory");
- goto finish;
- }
- }
-
- /* Alternate between checking for Blackbird events and processing
- user requests. */
- do
- {
- CheckEvents();
- } while (DoUserRequests());
- finish:
- puts("Exiting ...");
- vcEnd();
- return 0;
- }
-
-
-
- [LISTING THREE]
-
- /*--------------------------------------------------------------------
- (c) Copyright 1991, Gordon Free
- All Rights Reserved.
- ====================================================================
- Filename: FT_CB.C
- Project: DDJ Article
- $Author$
- $Revision$
- $Date$
- Purpose: Callback routines for Blackbird events
- ====================================================================*/
-
- /*-----Includes-----*/
- #include <stdio.h>
- #include "vcapi.h"
- #include "ft.h"
-
- /*------Global Variables ------*/
- extern SVCDATA_T svc[MAX_VCS]; /* service info for each VC */
- extern int fUpdateServices; /* set TRUE to display remotes */
-
- /* These routines are called at interrupt time, so no stack checking! */
- #pragma check_stack(off)
-
- /* Called whenever remote service list changes */
- void cbRemService (
- unsigned usNumSvcs /* Number of remote services */
- )
- {
- fUpdateServices = TRUE;
- }
- /* Called when remote machine connects to us as a client */
- SHORT cbListen (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Nothing at this time */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- )
- {
- svc[hVC-HVC_FIRST].fEvent.flags.ListenCallback = TRUE;
- svc[hVC-HVC_FIRST].sStatus = SHORT1FROMULONG(ul2);
- svc[hVC-HVC_FIRST].fActive = TRUE;
- return (FALSE);
- }
- /* Called when remote server acknowledges our connection request */
- SHORT cbConnect (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Nothing at this time */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- )
- {
- svc[hVC-HVC_FIRST].fEvent.flags.ConnectCallback = TRUE;
- svc[hVC-HVC_FIRST].sStatus = SHORT1FROMULONG(ul2);
- svc[hVC-HVC_FIRST].fActive = TRUE;
- return (FALSE);
- }
- /* Called anytime a VC is broken */
- SHORT cbDisConnect (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Nothing at this time */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- )
- {
- svc[hVC-HVC_FIRST].fEvent.flags.DisconnectCallback = TRUE;
- svc[hVC-HVC_FIRST].fActive = FALSE;
- return (FALSE);
- }
- /* Called when we've receive a data buffer from remote */
- SHORT cbRead (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Number of bytes received */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- )
- {
- svc[hVC-HVC_FIRST].fEvent.flags.ReadCallback = TRUE;
- svc[hVC-HVC_FIRST].lBytesSoFar = ul1;
- svc[hVC-HVC_FIRST].sStatus = SHORT1FROMULONG(ul2);
-
- return (FALSE);
- }
- /* Called when data has been successfully sent to remote */
- SHORT cbWrite (
- HANDLE hVC, /* Virtual connection handle */
- ULONG ul1, /* Nothing at this time */
- ULONG ul2 /* Status = SHORT1FROMUL( ul2 ) */
- )
- {
- svc[hVC-HVC_FIRST].fEvent.flags.WriteCallback = TRUE;
- svc[hVC-HVC_FIRST].sStatus = SHORT1FROMULONG(ul2);
-
- return (FALSE);
- }
- #pragma check_stack()
-
-